#include	"Vector4f.h"
#include	"Vector4i.h"
#include	<cmath>

const float Vector4f::EPSILON = 0.0001f;

Vector4f::Vector4f()
{
}

Vector4f::Vector4f(float x, float y, float z, float w)
{
	Set(x, y, z, w);
}

Vector4f::Vector4f(int x, int y, int z, int w)
{
	Set(x, y, z, w);
}

Vector4f::Vector4f(const Vector4f & vec)
{
	Set(vec);
}

Vector4f::Vector4f(const Vector4i & vec)
{
	Set(vec);
}

Vector4f::Vector4f(const float * arr)
{
	Set(arr);
}

Vector4f::Vector4f(const int * arr)
{
	Set(arr);
}

Vector4f::~Vector4f()
{
}

void Vector4f::Set(float x, float y, float z, float w)
{
	m_data[0] = x;
	m_data[1] = y;
	m_data[2] = z;
	m_data[3] = w;
}

void Vector4f::Set(int x, int y, int z, int w)
{
	m_data[0] = float(x);
	m_data[1] = float(y);
	m_data[2] = float(z);
	m_data[3] = float(w);
}

void Vector4f::Set(const float * arr)
{
	m_data[0] = arr[0];
	m_data[1] = arr[1];
	m_data[2] = arr[2];
	m_data[3] = arr[3];
}

void Vector4f::Set(const int * arr)
{
	m_data[0] = float(arr[0]);
	m_data[1] = float(arr[1]);
	m_data[2] = float(arr[2]);
	m_data[3] = float(arr[3]);
}

Vector4f::operator const float*() const
{
	return m_data;
}

Vector4f::operator float*()
{
	return m_data;
}

const Vector4f & Vector4f::operator+() const
{
	return *this;
}

Vector4f & Vector4f::operator+()
{
	return *this;
}

Vector4f Vector4f::operator-() const
{
	return Vector4f(-m_data[0], -m_data[1], -m_data[2], -m_data[3]);
}

Vector4f & Vector4f::operator=(const Vector4f & vec)
{
	Set(vec);
	return *this;
}

Vector4f & Vector4f::operator=(const Vector4i & vec)
{
	Set(vec);
	return *this;
}

Vector4f & Vector4f::operator+=(const Vector4f & vec)
{
	Set(m_data[0] + vec[0], m_data[1] + vec[1], m_data[2] + vec[2], m_data[3] + vec[3]);
	return *this;
}

Vector4f & Vector4f::operator+=(const Vector4i & vec)
{
	Set(m_data[0] + vec[0], m_data[1] + vec[1], m_data[2] + vec[2], m_data[3] + vec[3]);
	return *this;
}

Vector4f & Vector4f::operator-=(const Vector4f & vec)
{
	Set(m_data[0] - vec[0], m_data[1] - vec[1], m_data[2] - vec[2], m_data[3] - vec[3]);
	return *this;
}

Vector4f & Vector4f::operator-=(const Vector4i & vec)
{
	Set(m_data[0] - vec[0], m_data[1] - vec[1], m_data[2] - vec[2], m_data[3] - vec[3]);
	return *this;
}

Vector4f & Vector4f::operator*=(float num)
{
	Set(m_data[0] * num, m_data[1] * num, m_data[2] * num, m_data[3] * num);
	return *this;
}

Vector4f & Vector4f::operator*=(int num)
{
	Set(m_data[0] * num, m_data[1] * num, m_data[2] * num, m_data[3] * num);
	return *this;
}

Vector4f & Vector4f::operator/=(float num)
{
	Set(m_data[0] / num, m_data[1] / num, m_data[2] / num, m_data[3] / num);
	return *this;
}

Vector4f & Vector4f::operator/=(int num)
{
	Set(m_data[0] / num, m_data[1] / num, m_data[2] / num, m_data[3] / num);
	return *this;
}

Vector4f Vector4f::operator+(const Vector4f & vec) const
{
	return Vector4f(m_data[0] + vec[0], m_data[1] + vec[1], m_data[2] + vec[2], m_data[3] + vec[3]);
}

Vector4f Vector4f::operator+(const Vector4i & vec) const
{
	return Vector4f(m_data[0] + vec[0], m_data[1] + vec[1], m_data[2] + vec[2], m_data[3] + vec[3]);
}

Vector4f Vector4f::operator-(const Vector4f & vec) const
{
	return Vector4f(m_data[0] - vec[0], m_data[1] - vec[1], m_data[2] - vec[2], m_data[3] - vec[3]);
}

Vector4f Vector4f::operator-(const Vector4i & vec) const
{
	return Vector4f(m_data[0] - vec[0], m_data[1] - vec[1], m_data[2] - vec[2], m_data[3] - vec[3]);
}

Vector4f Vector4f::operator*(float num) const
{
	return Vector4f(m_data[0] * num, m_data[1] * num, m_data[2] * num, m_data[3] * num);
}

Vector4f Vector4f::operator*(int num) const
{
	return Vector4f(m_data[0] * num, m_data[1] * num, m_data[2] * num, m_data[3] * num);
}

Vector4f Vector4f::operator/(float num) const
{
	return Vector4f(m_data[0] / num, m_data[1] / num, m_data[2] / num, m_data[3] / num);
}

Vector4f Vector4f::operator/(int num) const
{
	return Vector4f(m_data[0] / num, m_data[1] / num, m_data[2] / num, m_data[3] / num);
}

Vector4f operator*(float num, const Vector4f & vec)
{
	return Vector4f(vec[0] * num, vec[1] * num, vec[2] * num, vec[3] * num);
}

Vector4f operator*(int num, const Vector4f & vec)
{
	return Vector4f(vec[0] * num, vec[1] * num, vec[2] * num, vec[3] * num);
}

bool Vector4f::operator==(const Vector4f & vec) const
{
	return ((vec[0] - Vector4f::EPSILON) <= m_data[0]) && (m_data[0] <= (vec[0] + Vector4f::EPSILON))
		&& ((vec[1] - Vector4f::EPSILON) <= m_data[1]) && (m_data[1] <= (vec[1] + Vector4f::EPSILON))
		&& ((vec[2] - Vector4f::EPSILON) <= m_data[2]) && (m_data[2] <= (vec[2] + Vector4f::EPSILON))
		&& ((vec[3] - Vector4f::EPSILON) <= m_data[3]) && (m_data[3] <= (vec[3] + Vector4f::EPSILON));
}

bool Vector4f::operator==(const Vector4i & vec) const
{
	return ((vec[0] - Vector4f::EPSILON) <= m_data[0]) && (m_data[0] <= (vec[0] + Vector4f::EPSILON))
		&& ((vec[1] - Vector4f::EPSILON) <= m_data[1]) && (m_data[1] <= (vec[1] + Vector4f::EPSILON))
		&& ((vec[2] - Vector4f::EPSILON) <= m_data[2]) && (m_data[2] <= (vec[2] + Vector4f::EPSILON))
		&& ((vec[3] - Vector4f::EPSILON) <= m_data[3]) && (m_data[3] <= (vec[3] + Vector4f::EPSILON));
}

bool operator==(const Vector4i & veci, const Vector4f & vecf)
{
	return ((veci[0] - Vector4f::EPSILON) <= vecf[0]) && (vecf[0] <= (veci[0] + Vector4f::EPSILON))
		&& ((veci[1] - Vector4f::EPSILON) <= vecf[1]) && (vecf[1] <= (veci[1] + Vector4f::EPSILON))
		&& ((veci[2] - Vector4f::EPSILON) <= vecf[2]) && (vecf[2] <= (veci[2] + Vector4f::EPSILON))
		&& ((veci[3] - Vector4f::EPSILON) <= vecf[3]) && (vecf[3] <= (veci[3] + Vector4f::EPSILON));
}

bool Vector4f::operator!=(const Vector4f & vec) const
{
	return ((vec[0] - Vector4f::EPSILON) > m_data[0]) || (m_data[0] > (vec[0] + Vector4f::EPSILON))
		|| ((vec[1] - Vector4f::EPSILON) > m_data[1]) || (m_data[1] > (vec[1] + Vector4f::EPSILON))
		|| ((vec[2] - Vector4f::EPSILON) > m_data[2]) || (m_data[2] > (vec[2] + Vector4f::EPSILON))
		|| ((vec[3] - Vector4f::EPSILON) > m_data[3]) || (m_data[3] > (vec[3] + Vector4f::EPSILON));
}

bool Vector4f::operator!=(const Vector4i & vec) const
{
	return ((vec[0] - Vector4f::EPSILON) > m_data[0]) || (m_data[0] > (vec[0] + Vector4f::EPSILON))
		|| ((vec[1] - Vector4f::EPSILON) > m_data[1]) || (m_data[1] > (vec[1] + Vector4f::EPSILON))
		|| ((vec[2] - Vector4f::EPSILON) > m_data[2]) || (m_data[2] > (vec[2] + Vector4f::EPSILON))
		|| ((vec[3] - Vector4f::EPSILON) > m_data[3]) || (m_data[3] > (vec[3] + Vector4f::EPSILON));
}

bool operator!=(const Vector4i & veci, const Vector4f & vecf)
{
	return ((veci[0] - Vector4f::EPSILON) > vecf[0]) || (vecf[0] > (veci[0] + Vector4f::EPSILON))
		|| ((veci[1] - Vector4f::EPSILON) > vecf[1]) || (vecf[1] > (veci[1] + Vector4f::EPSILON))
		|| ((veci[2] - Vector4f::EPSILON) > vecf[2]) || (vecf[2] > (veci[2] + Vector4f::EPSILON))
		|| ((veci[3] - Vector4f::EPSILON) > vecf[3]) || (vecf[3] > (veci[3] + Vector4f::EPSILON));
}

double Vector4f::LengthSquare() const
{
	return double(m_data[0] * m_data[0]) + double(m_data[1] * m_data[1]) + double(m_data[2] * m_data[2]) + double(m_data[3] * m_data[3]);
}

double Vector4f::Length() const
{
	return std::sqrt(double(m_data[0] * m_data[0]) + double(m_data[1] * m_data[1]) + double(m_data[2] * m_data[2]) + double(m_data[3] * m_data[3]));
}

void Vector4f::Normalize()
{
	double inverse_length = 1 / Length();
	Set(float(m_data[0] * inverse_length), float(m_data[1] * inverse_length), float(m_data[2] * inverse_length), float(m_data[3] * inverse_length));
}

Vector4f Vector4f::Normal() const
{
	double inverse_length = 1 / Length();
	return Vector4f(float(m_data[0] * inverse_length), float(m_data[1] * inverse_length), float(m_data[2] * inverse_length), float(m_data[3] * inverse_length));
}

